﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Pavilion
{
    public class CollectionDelta<T>
    {
        public IEnumerable<T> NewItems { get { return newItems; } }
        public IEnumerable<T> DeletedItems { get { return deletedItems; } }
        public IEnumerable<T> IdenticalItems { get { return identicalItems; } }

        private List<T> newItems, deletedItems, identicalItems;

        public CollectionDelta(IEnumerable<T> original, IEnumerable<T> current)
        {
            newItems = new List<T>();
            deletedItems = new List<T>();
            identicalItems = new List<T>();

            Load(original, current);
        }

        public CollectionDelta(IEnumerable<T> original, IEnumerable<T> current, Func<T, T, bool> comparer)
        {
            newItems = new List<T>();
            deletedItems = new List<T>();
            identicalItems = new List<T>();

            Load(original, current, comparer);
        }

        private void Load(IEnumerable<T> original, IEnumerable<T> current, Func<T, T, bool> comparer)
        {
            List<T> copyOfOriginal = new List<T>(original);

            foreach (T item in current)
            {
                T identicalitem = copyOfOriginal.FirstOrDefault(originalItem => comparer.Invoke(originalItem, item));

                if (identicalitem == null)
                    newItems.Add(item);
                else
                {
                    identicalItems.Add(item);
                    copyOfOriginal.Remove(identicalitem);
                }
            }

            deletedItems.AddRange(copyOfOriginal);
        }

        private void Load(IEnumerable<T> original, IEnumerable<T> current)
        {
            List<T> copyOfOriginal = new List<T>(original);

            foreach (T item in current)
            {
                if (!copyOfOriginal.Contains(item))
                    newItems.Add(item);
                else
                {
                    identicalItems.Add(item);
                    copyOfOriginal.Remove(item);
                }
            }

            deletedItems.AddRange(copyOfOriginal);
        }
    }
}
